#include <my_head.h>

void sig_func(int signum){
    if(SIGUSR1 == signum){
        wait(NULL); // 给子进程回收资源
    }
}

int main(int argc, const char *argv[]){
    if(3 != argc){
        printf("Usage : %s <IP> <PORT>\n", argv[0]);
        exit(EXIT_FAILURE);
    }
    // 创建套接字
    int sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if(-1 == sockfd)
        ERR_LOG("socket error");
    
    // 填充服务器网络信息结构体
    struct sockaddr_in serveraddr;
    serveraddr.sin_family = AF_INET;
    serveraddr.sin_port = htons(atoi(argv[2]));
    serveraddr.sin_addr.s_addr = inet_addr(argv[1]);
    socklen_t serveraddr_len = sizeof(serveraddr);

    // 将套接字和服务器网络信息结构体绑定
    if(-1 == bind(sockfd, (struct sockaddr *)&serveraddr, serveraddr_len))
        ERR_LOG("bind error");

    // 将套接字设置成被动监听状态
    if(-1 == listen(sockfd, 5))
        ERR_LOG("listen error");
    
    // 定义结构体 保存客户端的信息
    struct sockaddr_in clientaddr;
    socklen_t clientaddr_len = sizeof(clientaddr);

    // 捕捉SIGUSR1 信号
    signal(SIGUSR1, sig_func);

    pid_t pid = 0;
    int nbytes = 0;
    char buff[128] = {0};
    // 阻塞等待客户端连接
    int acceptfd = 0;
    while(1){
        printf("正在等待客户端连接...\n");
        if(-1 == (acceptfd = accept(sockfd, (struct sockaddr *)&clientaddr, &clientaddr_len))){
            ERR_LOG("accept error");
        }
        if(-1 == (pid = fork())){
            ERR_LOG("fork error");
        }else if(0 == pid){ // 子
            close(sockfd);
            printf("客户端[%s:%d]连接到服务器..\n", \
                inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port));
            while(1){
                // 收发数据
                // 接收客户端发来的数据
                if(-1 == (nbytes = recv(acceptfd, buff, sizeof(buff), 0))){
                    ERR_LOG("recv error");
                }else if(0 == nbytes){
                    printf("客户端[%s:%d]断开连接..\n", inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port));
                    break;
                }
                if(!strcmp(buff, "quit")){
                    printf("客户端[%s:%d]退出了..\n", inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port));
                    break;
                }
                // 处理数据（打印到终端）
                printf("客户端[%s:%d]发来数据[%s]\n", \
                        inet_ntoa(clientaddr.sin_addr), ntohs(clientaddr.sin_port), buff);
                // 组装应答消息
                strcat(buff, "--beijing");
                // 给客户端发送应答消息
                if(-1 == send(acceptfd, buff, sizeof(buff), 0)){
                    ERR_LOG("send error");
                }
            }
            // 关闭套接字
            close(acceptfd);
            // 给父进程发信号
            kill(getppid(), SIGUSR1);
            // 退出进程
            exit(EXIT_SUCCESS);
        }else if(0 < pid){ // 父进程
            close(acceptfd); // 父进程就不同做其他事儿了 回去接着等新客户端连接即可
        }
    }
    // 关闭套接字
    close(sockfd);

    return 0;
}